//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   AngleTraits.hh
 * \author Jeremy Roberts
 * \date   Jul 3, 2011
 * \brief  Angle traits for assisting in multi-d templating
 * \note   Copyright (C) 2011 Jeremy Roberts. 
 */
//---------------------------------------------------------------------------//
// $Rev::                                               $:Rev of last commit
// $Author::                                            $:Author of last commit
// $Date::                                              $:Date of last commit
//---------------------------------------------------------------------------//

#ifndef ANGLETRAITS_HH_
#define ANGLETRAITS_HH_

#include <iostream>
#include <vector>

#include "tran/Traits.hh"
#include "../utilities/Constants.hh"
#include "../utilities/Vector_Lite.hh"

namespace slabtran
{

//===========================================================================//
/*!
 * \class OmegaTraits
 * \brief Use \ref Vector_Lite for 2/3D and double for 1D \f$ \Omega \f$
 *
 */
//===========================================================================//
template <class D>
class OmegaTraits
{
public:
  typedef util::Vector_Lite<double, D::dimension> Omega;
};

template <>
class OmegaTraits<Dimension<1> >
{
public:
  typedef double Omega;
};

//===========================================================================//
/*!
 * \class QuadTraits
 * \brief Use \ref Vector_Lite for 2/3D and double for 1D \f$ \Omega \f$
 *
 */
//===========================================================================//
template <class D>
class QuadTraits
{
public:
  typedef std::vector<std::vector<double> > Angles;
};

template <>
class QuadTraits<Dimension<1> >
{
public:
  typedef std::vector<double> Angles;
};

//===========================================================================//
/*!
 * \struct Moments
 * \brief  Utility for describing moments characteristics.
 *
 * For a given \f$l\f$ and \f$m\f$, the index is defined by
 * \f[
 *    f^m_l = f[index] = \left\{
 *    \begin{array}{l l}
 *         f[l^2+l+m]       & \quad \text{for 3-d}           \\
 *         f[l^2+m+1]       & \quad \text{for 2-d and } m<0  \\
 *         f[l^2+m]         & \quad \text{for 2-d and } m>0  \\
 *         f[l]             & \quad \text{for 1-d}
 *    \end{array} \right.
 * \f]
 *
 */
//===========================================================================//
template <class D>
struct Moments
{
  /*!
   * \brief     Return the number of moments.
   * \param     N   Legendre order (as in \f$N\f$ of \f$P_N\f$).
   * \return        Number of moments.
   */
  static int number_moments(int N);

  /*!
   * \brief     Validate (l, m) pair for given order.
   * \param     l   Spherical harmonic degree.
   * \param     m   Spherical harmonic order.
   * \param     N   Legendre order (as in \f$N\f$ of \f$P_N\f$).
   * \return        Number of moments.
   */
  static bool valid(const int l, const int m, const int N);

  /*!
   * \brief     Return the cardinal moment index.
   * \param     l   Spherical harmonic degree.
   * \param     m   Spherical harmonic order.
   * \return        Cardinal moment index.
   */
  static int index(int l, int m = 0);
};

//===========================================================================//
/*!
 * \struct Norm
 * \brief  Normalization factor for angular integration.
 */
//===========================================================================//
template <class D>
struct Norm
{
  // \note It would be nice if I could just use the 1/4pi in Constants.hh
  const static double norm = 0.0795774715459476678;
};

template <>
struct Norm<_1D>
{
  const static double norm = 0.5;
};

} // end namespace slabtran

//---------------------------------------------------------------------------//
// INLINE FUNCTIONS
//---------------------------------------------------------------------------//

#include "AngleTraits.i.hh"

#endif /* ANGLETRAITS_HH_ */

//---------------------------------------------------------------------------//
//              end of AngleTraits.hh
//---------------------------------------------------------------------------//
